//
// Constant Buffer Variables
//

Texture2D Texture2D1;
SamplerState samLinear
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

//TextureCube g_txEnvMap;
//SamplerState samLinearClamp
//{
    //Filter = MIN_MAG_MIP_LINEAR;
    //AddressU = Clamp;
    //AddressV = Clamp;
//};

cbuffer cbConstant
{
    float3 vLightDir = float3(0, -1, 0);
    //float3 vLightDir = float3(-0.577,0.577,-0.577);
};

cbuffer cbChangesEveryFrame
{
    matrix World;
    matrix View;
    matrix Projection;
	float3 Kd;
};

struct VS_INPUT
{
    float3 Pos          : POSITION;         //position
    float3 Norm         : NORMAL;           //normal
    float2 Tex          : TEXCOORD0;        //texture coordinate
};

struct PS_INPUT
{
    float4 Pos : SV_POSITION;
    float3 Norm : TEXCOORD0;
    float2 Tex : TEXCOORD1;
    float3 ViewR : TEXCOORD2;
};

//--------------------------------------------------------------------------------------
// DepthStates
//--------------------------------------------------------------------------------------
DepthStencilState EnableDepth
{
    DepthEnable = TRUE;
    DepthWriteMask = ALL;
    DepthFunc = LESS_EQUAL;
};

BlendState NoBlending
{
    AlphaToCoverageEnable = FALSE;
    BlendEnable[0] = FALSE;
};

//
// Vertex Shader
//
PS_INPUT VS( VS_INPUT input )
{
    PS_INPUT output = (PS_INPUT)0;
    
    output.Pos = mul( float4(input.Pos,1), World );
    output.Pos = mul( output.Pos, View );
	output.ViewR = output.Pos.xyz;
    output.Pos = mul( output.Pos, Projection );
    output.Norm = mul( input.Norm, (float3x3)World );
    output.Tex = input.Tex;
    
    // Calculate the reflection vector
    //float3 viewNorm = mul( output.Norm, (float3x3)View );
    //output.ViewR = reflect( viewNorm, float3(0,0,-1.0) );
    
    return output;
}

//
// Pixel Shader
//
float4 PS( PS_INPUT input) : SV_Target
{
    // Calculate lighting assuming light color is <1,1,1,1>
    float fLighting = saturate( dot( input.Norm, normalize(vLightDir) ) ) * 0.8f + 0.1f;
	float4 cTotal = float4(Texture2D1.Sample(samLinear, input.Tex).xyz * fLighting, 1.0f);
	   
    // Add diffuse to reflection and go
  //  float4 cTotal = float4(Kd.x * fLighting, Kd.y * fLighting, Kd.z * fLighting, 1.0f);
    return cTotal;
}

float4 PSBlinnPhong(PS_INPUT input) : SV_Target
{
    float diffuse = saturate( dot( input.Norm, normalize(vLightDir) ) ) * 0.2f + 0.05f;
	
	float3 lightV = normalize(mul(vLightDir, (float3x3)View));
	float3 normV = normalize(mul(input.Norm, (float3x3)View));
	float3 H = normalize(lightV - input.ViewR);
	float HdotN = max(0.0f, dot(normV, H));
	float specular = pow(HdotN, 30);
	float coeff = diffuse + specular;

	return float4(Kd.x * coeff, Kd.y * coeff, Kd.z * coeff, 1.0f);
}


RasterizerState CullFront
{
	CullMode = FRONT;
};

RasterizerState CullBack
{
	CullMode = BACK;
};


//
// Technique
//
technique10 Render
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PSBlinnPhong() ) );
        //SetPixelShader( CompileShader( ps_4_0, PS() ) );
        
        SetDepthStencilState( EnableDepth, 0 );
        SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
		SetRasterizerState(CullBack);
    }
}

technique10 RenderBack
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PSBlinnPhong() ) );
        //SetPixelShader( CompileShader( ps_4_0, PS() ) );
        
        SetDepthStencilState( EnableDepth, 0 );
        SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
		SetRasterizerState(CullFront);
    }
}
